﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using CoolCode.Linq;

namespace CoolCode.Data
{
    public interface IRepository<T> : IQueryable<T>, IEnumerable<T>, IDisposable
    { 
        void Insert(T entity);
        void Insert(IEnumerable<T> list);

        void Update(T entity);
        //void Update(T entity, T original);
        void Update(IEnumerable<T> list);
		
		 
		/// <summary>
		/// 更新
		/// </summary>  
		/// <param name="predicate">查询条件表达式</param>
		/// <param name="updater">更新表达式</param>
		/// <returns>影响的行数</returns>
		int Update(Expression<Func<T, bool>> predicate, Expression<Func<T, T>> updater);
		 

        void Delete(T entity);
        void Delete(IQueryable<T> query);
        void Delete(IEnumerable<T> list);
        void Delete(Expression<Func<T, bool>> predicate);

        //IQueryable<T> Query();
        //IQueryable<T> Query(Expression<Func<T, bool>> predicate);
        //IQueryable<T> In<P>(Expression<Func<T, P>> property,  IList<P> values);
        //IQueryable<T> Where(Expression<Func<T, bool>> predicate);

        //List<T> List(IQueryable<T> query, bool withNoLock);

        T Get(Expression<Func<T, bool>> predicate);


        //ISingleResult<TResult> ExecuteStoredProcedure<TResult>(object instance, MethodInfo method, params object[] parameters);

        //IMultipleResults ExecuteStoredProcedure(object instance, MethodInfo method, params object[] parameters);
    }

    public static class RepositoryExtension
    {
        //public static IPaginatedList<T> Paging<T>(this IRepository<T> rep, PageParam p)
        //{
        //    var q = rep ;
        //    return new PaginatedList<T>(q, p);
        //}

        //public static IPaginatedList<T> Paging<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate, PageParam p) 
        //{
        //    var q = rep.Where(predicate);
        //    return new PaginatedList<T>(q, p);
        //}


        //public static IPaginatedList<T> Paging<T>(this IRepository<T> rep, Func<IQueryable<T>, IQueryable<T>> handle, PageParam p) 
        //{
        //    var q = handle(rep );
        //    return new PaginatedList<T>(q, p);
        //}

        //public static IPaginatedList<T> Paging<T>(this IRepository<T> rep, Func<IEnumerable<T>, IEnumerable<T>> handle, PageParam p) 
        //{
        //    var q = handle(rep );
        //    return new PaginatedList<T>(q, p);
        //}         

        public static List<T> List<T>(this IRepository<T> rep) 
        {
            var q = rep ;
            return q.ToList();
        }

        public static List<T> List<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate) 
        {
            var q = rep.Where(predicate);
            return q.ToList();
        }

        public static bool Contains<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate)   
        {
            var q = rep.Where(predicate);
            return q.Count() > 0;
        }

        public static void Update<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate, Action<T> action) 
        {
            var list = rep.List(predicate);
            foreach (T entity in list)
                action(entity);
        }

        public static void Save<T>(this IRepository<T> rep, T t) where T : IEntity
        {
            T entity = rep.Get(c => c.ID == t.ID);
            if (entity != null)
            {
                rep.Delete(entity);
            }
            rep.Insert(t);           
        }

        public static bool Contains<T>(this IRepository<T> rep, int id) where T : IEntity
        {
            return rep.Contains(c => c.ID == id);
        }

        public static T Get<T>(this IRepository<T> rep, int id) where T : IEntity
        {
            return rep.Get(c => c.ID == id);
        }

        public static void Delete<T>(this IRepository<T> rep, int id) where T : IEntity
        {
             rep.Delete(c => c.ID == id);
        }

        public static void Delete<T>(this IRepository<T> rep, int[] ids) where T : IEntity
        {
            rep.Delete(c => ids.Contains( c.ID));
        }
    } 

    //public static class RepositoryExtension
    //{
    //    public static PaginatedList<T> Paging<T>(this IRepository<T> rep, PageParam p) 
    //    {
    //        var q = rep.Query();
    //        return new PaginatedList<T>(q, p);
    //    }

    //    public static PaginatedList<T> Paging<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate, PageParam p) 
    //    {
    //        var q = rep.Query(predicate);
    //        return new PaginatedList<T>(q, p);
    //    }


    //    public static PaginatedList<T> Paging<T>(this IRepository<T> rep, Func<IQueryable<T>, IQueryable<T>> handle, PageParam p) 
    //    {
    //        var q = handle(rep.Query());
    //        return new PaginatedList<T>(q, p);
    //    }

    //    public static PaginatedList<T> Paging<T>(this IRepository<T> rep, Func<IEnumerable<T>, IEnumerable<T>> handle, PageParam p) 
    //    {
    //        var q = handle(rep.Query());
    //        return new PaginatedList<T>(q, p);
    //    }

    //    public static List<T> List<T>(this IRepository<T> rep) 
    //    {
    //        var q = rep.Query();
    //        return q.ToList();
    //    }

    //    public static List<T> List<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate) 
    //    {
    //        var q = rep.Query(predicate);
    //        return q.ToList();
    //    }

    //    public static bool Contains<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate)   
    //    {
    //        var q = rep.Query(predicate);
    //        return q.Count() > 0;
    //    }

    //    public static void Update<T>(this IRepository<T> rep, Expression<Func<T, bool>> predicate, Action<T> action) 
    //    {
    //        var list = rep.List(predicate);
    //        foreach (T entity in list)
    //            action(entity);
    //    }
    //} 
}
